using NICWebApi.Extensions.Caching.Interfaces;
using NICWebApi.Extensions.Caching.Options;

namespace NICWebApi.Extensions.Caching.Implementations;

/// <summary>
/// 默认缓存键生成器实现
/// 提供统一的缓存键生成策略，支持前缀、分隔符和类型感知的键生成
/// </summary>
public class DefaultCacheKeyGenerator : ISimpleCacheKeyGenerator
{
    private readonly string _prefix;
    private readonly string _separator;
    private static readonly Regex _invalidKeyCharsRegex = new(@"[\s{}()/\\<>:*%]", RegexOptions.Compiled);

    /// <summary>
    /// 初始化默认缓存键生成器
    /// </summary>
    /// <param name="options">缓存选项，包含前缀和分隔符配置</param>
    public DefaultCacheKeyGenerator(IOptions<CachingOptions> options)
    {
        var cachingOptions = options?.Value ?? new CachingOptions();
        _prefix = cachingOptions.KeyPrefix ?? string.Empty;
        _separator = cachingOptions.KeySeparator ?? ":";
    }

    /// <summary>
    /// 生成缓存键
    /// </summary>
    /// <param name="args">缓存键参数，支持多个参数组合</param>
    /// <returns>规范化后的缓存键</returns>
    public string Generate(params object[] args)
    {
        if (args == null || args.Length == 0)
        {
            return _prefix;
        }

        var builder = new StringBuilder();

        if (!string.IsNullOrEmpty(_prefix))
        {
            builder.Append(_prefix);
        }

        foreach (var arg in args)
        {
            if (arg != null)
            {
                if (builder.Length > 0 && !string.IsNullOrEmpty(_separator))
                {
                    builder.Append(_separator);
                }
                builder.Append(arg.ToString());
            }
        }

        return NormalizeKey(builder.ToString());
    }

    /// <summary>
    /// 生成缓存键（兼容旧接口）
    /// </summary>
    /// <param name="baseKey">基础键</param>
    /// <param name="parameters">额外参数</param>
    /// <returns>生成的缓存键</returns>
    public string Generate(string baseKey, params object[] parameters)
    {
        if (string.IsNullOrEmpty(baseKey))
        {
            throw new ArgumentNullException(nameof(baseKey), "基础键不能为空");
        }

        var allParams = new object[parameters.Length + 1];
        allParams[0] = baseKey;
        Array.Copy(parameters, 0, allParams, 1, parameters.Length);

        return Generate(allParams);
    }

    /// <summary>
    /// 生成带前缀的缓存键
    /// </summary>
    /// <param name="prefix">前缀</param>
    /// <param name="keyParts">键的各个部分</param>
    /// <returns>生成的缓存键</returns>
    public string GenerateWithPrefix(string prefix, params object[] keyParts)
    {
        if (string.IsNullOrEmpty(prefix))
        {
            throw new ArgumentNullException(nameof(prefix), "前缀不能为空");
        }

        var allParams = new object[keyParts.Length + 1];
        allParams[0] = prefix;
        Array.Copy(keyParts, 0, allParams, 1, keyParts.Length);

        return Generate(allParams);
    }

    /// <summary>
    /// 生成基于类型的缓存键
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="keyParts">键的各个部分</param>
    /// <returns>生成的缓存键</returns>
    public string GenerateWithType<T>(params object[] keyParts)
    {
        var typeName = typeof(T).Name;
        var allParams = new object[keyParts.Length + 1];
        allParams[0] = typeName;
        Array.Copy(keyParts, 0, allParams, 1, keyParts.Length);

        return Generate(allParams);
    }

    /// <summary>
    /// 生成模式匹配键（用于模式匹配删除等操作）
    /// </summary>
    /// <param name="pattern">匹配模式</param>
    /// <returns>规范化后的模式匹配键</returns>
    public string GeneratePatternKey(string pattern)
    {
        if (string.IsNullOrEmpty(pattern))
        {
            return _prefix + "*";
        }

        var key = !string.IsNullOrEmpty(_prefix)
            ? $"{_prefix}{_separator}{pattern}"
            : pattern;

        return NormalizeKey(key);
    }

    /// <summary>
    /// 根据类型生成缓存键
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="args">附加参数</param>
    /// <returns>规范化后的缓存键</returns>
    public string GenerateForType<T>(params object[] args)
    {
        var type = typeof(T);
        var typeName = type.FullName ?? type.Name;

        if (args == null || args.Length == 0)
        {
            return Generate(typeName);
        }

        var combinedArgs = new object[args.Length + 1];
        combinedArgs[0] = typeName;
        Array.Copy(args, 0, combinedArgs, 1, args.Length);

        return Generate(combinedArgs);
    }

    /// <summary>
    /// 为特定类型生成缓存键
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="baseKey">基础键</param>
    /// <returns>带有类型信息的缓存键</returns>
    public string GenerateForType<T>(string baseKey)
    {
        if (string.IsNullOrEmpty(baseKey))
        {
            throw new ArgumentNullException(nameof(baseKey), "基础键不能为空");
        }

        var typeName = typeof(T).Name;
        return Generate(typeName, baseKey);
    }

    /// <summary>
    /// 规范化缓存键
    /// 移除无效字符，确保键的合法性
    /// </summary>
    /// <param name="key">原始键</param>
    /// <returns>规范化后的键</returns>
    public string NormalizeKey(string key)
    {
        if (string.IsNullOrEmpty(key))
        {
            return string.Empty;
        }

        // 移除无效字符
        var normalizedKey = _invalidKeyCharsRegex.Replace(key, "_");

        // 确保键不以分隔符开头或结尾
        normalizedKey = normalizedKey.Trim(_separator[0]);

        return normalizedKey;
    }
}